package com.ihr360.payroll.model.dto.attendance.report;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.ihr360.authority.sharing.entityhandler.UserResourceHandler;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.payroll.model.dto.attendance.report.embeddable.AttendanceReportFixedPart;
import com.ihr360.payroll.model.dto.attendance.report.embeddable.AttendanceReportFlexPart;
import com.ihr360.payroll.model.dto.salary.embeddable.StaffInfoSnapshot;
import com.ihr360.shared.entitywithlistener.NumberIdWithTimeAndCompanyId;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 实际出勤天数（天）
 * 应出勤天数（天）
 * 法定计薪天数（天）
 * 月计薪天数（天）
 * 平日加班小时-标准（小时）
 * 周末加班小时-标准（小时）
 * 节假日加班小时-标准（小时）
 * 工作日加班累计（小时）
 * 休息日加班累计（小时）
 * 节假日加班累计（小时）
 * 扣薪病假时长（小时）
 * 全薪病假时长（小时）
 * 事假时长（小时）
 * 产假时长（小时）
 * 工时调整-综合（小时）
 * 节假日加班小时-综合（小时）
 * 月工作日工时-综合（小时）
 * 季工作日工时-综合（小时）
 * 年工作日工时-综合（小时）
 * 年假时长（小时）
 * 调休时长（小时）
 * 迟到次数（次数）
 * 早退次数（次数）
 *  签到遗漏次数（次数）
 *  签退遗漏次数（次数）
 *  累计迟到分钟数（分钟）
 *  累计早退分钟数（分钟）
 *  缺勤次数（次数）
 * */
@Entity
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"companyId", "year", "month", "staffId", "salaryPlanId"}))
@JsonIgnoreProperties(ignoreUnknown = true)
@EntityListeners(value = {UserResourceHandler.class})
public class AttendanceMonthlyReport extends NumberIdWithTimeAndCompanyId<Long> {
    @Embedded
    private StaffInfoSnapshot staffInfo;
    private int year;
    private int month;
    @Column(columnDefinition = "date")
    private Date startDate;
    @Column(columnDefinition = "date")
    private Date endDate;

    /**
     * 薪资方案id
     * */
    @Column(nullable = false)
    private Long salaryPlanId;
    /**
     * 固定字段
     */
    @Embedded
    private AttendanceReportFixedPart fixedPart;

    /**
     * 弹性字段
     */
    @Column(columnDefinition = "text", name = "flexPart")
    @Type(type = "json")
    private AttendanceReportFlexPart flexPart;

    /**
     * 考勤汇总
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false)
    private AttendanceMonthlyReportSummary summary;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "monthlyReport", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<AttendanceBill> attendanceBillList = new ArrayList<>();

    public Map<String, Double> toDynamicCells() {
        Map<String, Double> map;

        if (flexPart != null && CollectionUtils.isNotEmpty(flexPart.getItems())) {
            map = new HashMap<>(flexPart.getItems());
        } else {
            map = new HashMap<>(20);
        }
        if (fixedPart != null) {
            /**
             * 实际出勤天数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.WORKING_DAYS, fixedPart.getWorkingdays());
            /**
             * 应出勤天数（不包含法定节假日）
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SUPPOSED_WORKING_DAYS, fixedPart.getSupposedworkingdays());

            /**
             * 月计薪天数（本人本月计薪天数）
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.PAID_DAYS, fixedPart.getPaiddays());

            /**
             * 缺勤次数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.ABSENCE_FROM_DUTY_DAYS, fixedPart.getAbsencefromdutydays());

            /**
             * 平日加班小时-标准
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.OT_HOURS_150, fixedPart.getOthours150());
            /**
             * 周末加班小时-标准
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.OT_HOURS_200, fixedPart.getOthours200());
            /**
             * 节假日加班小时-标准
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.OT_HOURS_300, fixedPart.getOthours300());

            /**
             * 工作日加班累计（小时）
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.WORKINGDAY_OVERTIME_CAL, fixedPart.getWorkingdayovertimecal());

            /**
             * 休息日加班累计（小时）
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.RESTDAY_OVERTIME_CAL, fixedPart.getRestdayovertimecal());

            /**
             * 节假日加班累计（小时）
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.HOLIDAY_OVERTIME_CAL, fixedPart.getHolidayovertimecal());

            /**
             * 病假时长
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SICK_LEAVE_COUNT, fixedPart.getSickleavecnt());

            /**
             * 全薪病假时长
             */
            //map.put(AttendanceReportFixedPart.Field.PAY_SICK_LEAVE_COUNT, fixedPart.getSickleavecnt());
            /**
             * 事假天数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.UNPAID_LEAVE_COUNT, fixedPart.getUnpaidleavecnt());
            /**
             * 产假天数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.MATERNITY_COUNT, fixedPart.getMaternitycnt());


            /**
             * 工时调整-综合
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SYNTHETICAL_ADJUST, fixedPart.getSyntheticaladjust());

            /**
             * 节假日加班小时-综合
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SYNTHETICAL_OTHOURS_300, fixedPart.getSyntheticalothours300());
            /**
             * 月工作日工时-综合
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SYNTHETICAL_WORKHOURMONTH, fixedPart.getSyntheticalworkhourmonth());
            /**
             * 季工作日工时-综合
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SYNTHETICAL_WORKHOURQUARTER, fixedPart.getSyntheticalworkhourquarter());
            /**
             * 年工作日工时-综合
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SYNTHETICAL_WORKHOURYEAR, fixedPart.getSyntheticalworkhouryear());
            /**
             * 年假时长
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.ANNUAL_LEAVETIME, fixedPart.getAnnualleavetime());
            /**
             * 调休时长
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.REST_HOURS, fixedPart.getResthours());
            /**
             * 迟到次数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.LATE_ARRIVALS, fixedPart.getLatearrivals());
            /**
             * 早退次数
             */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.RETURN_EARLY, fixedPart.getReturnearly());
            /**
             *  签到遗漏次数（原始次数）
             * */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SIGN_IN_MISS, fixedPart.getSigninmiss());
            /**
             *  签退遗漏次数（原始次数）
             * */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.SIGN_OUT_MISS, fixedPart.getSignoutmiss());
            /**
             *  累计迟到分钟数
             * */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.LATE_MINUTES, fixedPart.getLateminutes());
            /**
             *  累计早退分钟数
             * */
            map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.EARLY_MINUTES, fixedPart.getEarlyminutes());

            /**
             *  缺勤次数
             * */
            //map.put(com.ihr360.attendance.AttendanceReportFixedPart.Field.ABSENCE_FROM_DUTY, fixedPart.getAbsencefromduty());
        }
        return map;
    }

    @JsonIgnore
    public List<AttendanceBill> getAttendanceBillList() {
        return attendanceBillList;
    }

    public void setAttendanceBillList(List<AttendanceBill> attendanceBillList) {
        this.attendanceBillList = attendanceBillList;
    }

    @JsonIgnore
    public AttendanceMonthlyReportSummary getSummary() {
        return summary;
    }

    public void setSummary(AttendanceMonthlyReportSummary summary) {
        this.summary = summary;
    }

    public StaffInfoSnapshot getStaffInfo() {
        return staffInfo;
    }

    public void setStaffInfo(StaffInfoSnapshot staffInfo) {
        this.staffInfo = staffInfo;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public AttendanceReportFixedPart getFixedPart() {
        return fixedPart;
    }

    public void setFixedPart(AttendanceReportFixedPart fixedPart) {
        this.fixedPart = fixedPart;
    }

    public AttendanceReportFlexPart getFlexPart() {
        return flexPart;
    }

    public void setFlexPart(AttendanceReportFlexPart flexPart) {
        this.flexPart = flexPart;
    }

    public Long getSalaryPlanId() {
        return salaryPlanId;
    }

    public void setSalaryPlanId(Long salaryPlanId) {
        this.salaryPlanId = salaryPlanId;
    }
}